package opt_reflect

import (
	"fmt"
	"reflect"
	"unsafe"
)

func reflect_type(in interface{}) {

	// 接口转型
	var i = in.(int)

	fmt.Println("==========i", i)
	// 反射所有类型
	typeIn := reflect.TypeOf(in)
	fmt.Println("in type is", typeIn)

	kind := typeIn.Kind()

	fmt.Println("Kind is ", kind)

	switch kind {
	case reflect.Float64:
		fmt.Printf("a is float64\n")
	case reflect.String:
		fmt.Printf("a is Srt\n")
	}

}

func reflect_value(in interface{}) {
	of := reflect.ValueOf(in)
	fmt.Println("=========of======", of)

	kind := of.Kind()
	fmt.Println("=========kind======", kind)

	fmt.Println("转为 flaot 类型 ", of.Float())

	// 不能写
	if of.CanSet() {
		of.SetFloat(4.5)
	}
	fmt.Println("in finish is", of.Float())
}

type User struct {
	Id         int `json:"id"`
	Name       string
	Age        int32
	GenerateId func(a int)
}

func (u User) SetAge() {
	u.Age = 20
	fmt.Println("user is ", u)
}

func reflect_struct(o interface{}) {
	// 相当于 Class 对象
	ref_type := reflect.TypeOf(o)

	fmt.Println("ref_type struct is ：", ref_type)

	fmt.Println("ref_type struct Name is ：", ref_type.Name())

	fmt.Println("ref_type struct Files Number  ：", ref_type.NumField())
	fmt.Println("ref_type struct Method Number :", ref_type.NumMethod())

	ref_value := reflect.ValueOf(o)

	for i := 0; i < ref_type.NumField(); i++ {
		field := ref_type.Field(i)
		fmt.Println("ref_type File Name： ", field.Name, "Type ：",
			field.Type, "Tag：", field.Tag, "value is ", ref_value.Field(i))

		value := ref_value.Field(i)
		// 只允许引用类型可以写
		if value.CanSet() {
			file_kind := value.Kind()
			switch file_kind {
			case reflect.Int:
				value.SetInt(2)
			case reflect.String:
				value.SetString("ste12344")
			case reflect.Int32:
				value.SetInt(3)
			case reflect.Func:
				f := func(a int) {
					fmt.Println("======")
				}
				value.SetPointer(unsafe.Pointer(&f))
			}
		}
	}

	fmt.Println("o finish  is ", o)
	fmt.Println("ref_value finish  is ", ref_value)
	user := o.(User)
	user.GenerateId(2)

}

func reflect_struct_2() {

	// type is value
	user := User{
		10,
		"user2",
		12,
		func(a int) {
			fmt.Println("original func is ", a)
		},
	}
	value_passing := reflect.ValueOf(user)
	fmt.Println("value_passing King is Name ", value_passing.Kind().String())
	fmt.Println("value_passing String :", value_passing.String())
	fmt.Println("value_passing is CanSet  :", value_passing.CanSet())
	fmt.Println("value_passing is ", value_passing.Field(0).CanSet(), "canset")

	// 返回引用类型值
	references_value := reflect.ValueOf(&user).Elem()
	fmt.Println("==========", references_value.CanSet())

}
